home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / Tool Chest / Games / Game Sample Code / SpriteWorld 1.0b3 / Sources / SpriteWorld.c < prev    next >
Encoding:
Text File  |  1993-06-12  |  25.8 KB  |  922 lines  |  [TEXT/KAHL]

  1. ///--------------------------------------------------------------------------------------
  2. //    SpriteWorld.c
  3. //
  4. //    Created:    Wednesday, May 29, 1991 at 10:43:28 PM
  5. //    By:        Tony Myles
  6. //
  7. //    Copyright: © 1991-93 Tony Myles, All rights reserved worldwide.
  8. //
  9. //    Description:    implementation of the sprite world architecture
  10. ///--------------------------------------------------------------------------------------
  11.  
  12.  
  13. #ifndef __QUICKDRAW__
  14. #include <QuickDraw.h>
  15. #endif
  16.  
  17. #ifndef __MEMORY__
  18. #include <Memory.h>
  19. #endif
  20.  
  21. #ifndef __GESTALTEQU__
  22. #include <GestaltEqu.h>
  23. #endif
  24.  
  25. #ifndef __SPRITEWORLDUTILS__
  26. #include <SpriteWorldUtils.h>
  27. #endif
  28.  
  29. #ifndef __SPRITEWORLD__
  30. #include <SpriteWorld.h>
  31. #endif
  32.  
  33. #ifndef __SPRITELAYER__
  34. #include <SpriteLayer.h>
  35. #endif
  36.  
  37. #ifndef __SPRITE__
  38. #include <Sprite.h>
  39. #endif
  40.  
  41. #ifndef __FRAME__
  42. #include <Frame.h>
  43. #endif
  44.  
  45.  
  46. ///--------------------------------------------------------------------------------------
  47. //    SWEnterSpriteWorld
  48. ///--------------------------------------------------------------------------------------
  49.  
  50. SW_PASCAL OSErr SWEnterSpriteWorld(void)
  51. {
  52.     OSErr err;
  53.     long    versionNumber;
  54.  
  55.         // make sure we can run in this environment
  56.     err = Gestalt(gestaltTimeMgrVersion, &versionNumber);
  57.  
  58.     if ((err != noErr) || (versionNumber < gestaltStandardTimeMgr))
  59.     {
  60.         err = kTimeMgrNotPresentErr;
  61.     }
  62.  
  63.     return err;
  64. }
  65.  
  66.  
  67. ///--------------------------------------------------------------------------------------
  68. //    SWExitSpriteWorld
  69. ///--------------------------------------------------------------------------------------
  70.  
  71. SW_PASCAL void SWExitSpriteWorld(void)
  72. {
  73.     // nothing happens here right now, but that might change later
  74. }
  75.  
  76.  
  77. ///--------------------------------------------------------------------------------------
  78. //    SWCreateSpriteWorld
  79. ///--------------------------------------------------------------------------------------
  80.  
  81. SW_PASCAL OSErr SWCreateSpriteWorld(
  82.     SpriteWorldPtr *spriteWorldP,
  83.     FramePtr windowFrameP,
  84.     FramePtr backFrameP,
  85.     FramePtr loadFrameP)
  86. {
  87.     OSErr err;
  88.     CGrafPtr curGrafP;
  89.     GDHandle curGDeviceH;
  90.     FramePtr tempFrameP;
  91.     SpriteWorldPtr tempSpriteWorldP;
  92.  
  93.     err = noErr;
  94.     *spriteWorldP = NULL;
  95.  
  96.     tempSpriteWorldP = (SpriteWorldPtr)NewPtrClear((Size)sizeof(SpriteWorldRec));
  97.  
  98.     if (tempSpriteWorldP != NULL)
  99.     {
  100.         tempSpriteWorldP->windowFrameP = windowFrameP;
  101.         tempSpriteWorldP->backFrameP = backFrameP;
  102.         tempSpriteWorldP->loadFrameP = loadFrameP;
  103.         tempSpriteWorldP->eraseDrawProc = SWStdDrawProc;
  104.         tempSpriteWorldP->screenDrawProc = SWStdMaskDrawProc;
  105.  
  106.         *spriteWorldP = tempSpriteWorldP;
  107.     }
  108.     else
  109.     {
  110.         err = MemError();
  111.     }
  112.  
  113.     return err;
  114. }
  115.  
  116.  
  117. ///--------------------------------------------------------------------------------------
  118. //    SWCreateSpriteWorldFromWindow
  119. ///--------------------------------------------------------------------------------------
  120.  
  121. SW_PASCAL OSErr SWCreateSpriteWorldFromWindow(
  122.     SpriteWorldPtr* spriteWorldP,
  123.     CWindowPtr srcWindowP,
  124.     Rect* worldRect)
  125. {
  126.     OSErr err;
  127.     CGrafPtr savePort;
  128.     GDHandle saveGDevice;
  129.     FramePtr windowFrameP, backFrameP, loadFrameP;
  130.     Rect tempRect;
  131.  
  132.     *spriteWorldP = NULL;
  133.     windowFrameP = backFrameP = loadFrameP = NULL;
  134.  
  135.     tempRect = (worldRect == NULL) ? srcWindowP->portRect : *worldRect;
  136.  
  137.     GetPort((GrafPtr*)&savePort);
  138.     SetPort((GrafPtr)srcWindowP);
  139.  
  140.         // create window frame
  141.     err = SWCreateFrame(&windowFrameP, srcWindowP, &tempRect);
  142.  
  143.     if (err == noErr)
  144.     {
  145.             // create back drop frame
  146.         err = SWCreateFrame(&backFrameP, NULL, &tempRect);
  147.     }
  148.  
  149.     if (err == noErr)
  150.     {
  151.             // create loader frame
  152.         err = SWCreateFrame(&loadFrameP, NULL, &tempRect);
  153.     }
  154.  
  155.     if (err == noErr)
  156.     {
  157.             // create sprite world
  158.         err = SWCreateSpriteWorld(spriteWorldP, windowFrameP, backFrameP, loadFrameP);
  159.     }
  160.  
  161.     if (err != noErr)
  162.     {
  163.             // an error occurred so dispose of anything we managed to create
  164.  
  165.         if (windowFrameP != NULL)
  166.         {
  167.             SWDisposeFrame(windowFrameP);
  168.         }
  169.  
  170.         if (backFrameP != NULL)
  171.         {
  172.             SWDisposeFrame(backFrameP);
  173.         }
  174.  
  175.         if (loadFrameP != NULL)
  176.         {
  177.             SWDisposeFrame(loadFrameP);
  178.         }
  179.     }
  180.  
  181.     SetPort((GrafPtr)savePort);
  182.  
  183.     return err;
  184. }
  185.  
  186.  
  187. ///--------------------------------------------------------------------------------------
  188. //    SWDisposeSpriteWorld
  189. ///--------------------------------------------------------------------------------------
  190.  
  191. SW_PASCAL void SWDisposeSpriteWorld(
  192.     SpriteWorldPtr spriteWorldP)
  193. {
  194.     if (spriteWorldP != NULL)
  195.     {
  196.         SWDisposeFrame(spriteWorldP->backFrameP);
  197.  
  198.         SWDisposeFrame(spriteWorldP->loadFrameP);
  199.  
  200.         spriteWorldP->windowFrameP->framePort.colorGrafP = NULL;
  201.         SWDisposeFrame(spriteWorldP->windowFrameP);
  202.  
  203.         DisposePtr((Ptr)spriteWorldP);
  204.     }
  205. }
  206.  
  207.  
  208. ///--------------------------------------------------------------------------------------
  209. //    SWAddSpriteLayer
  210. ///--------------------------------------------------------------------------------------
  211.  
  212. SW_PASCAL void SWAddSpriteLayer(
  213.     SpriteWorldPtr spriteWorldP,
  214.     SpriteLayerPtr newSpriteLayerP)
  215. {
  216.     SpriteLayerPtr tailSpriteLayerP = spriteWorldP->tailSpriteLayerP;
  217.  
  218.     if (tailSpriteLayerP != NULL)
  219.     {
  220.             // doubly link the new layer
  221.         tailSpriteLayerP->nextSpriteLayerP = newSpriteLayerP;
  222.         newSpriteLayerP->prevSpriteLayerP = tailSpriteLayerP;
  223.         newSpriteLayerP->nextSpriteLayerP = NULL;
  224.     }    
  225.     else
  226.     {
  227.         newSpriteLayerP->prevSpriteLayerP = NULL;
  228.         newSpriteLayerP->nextSpriteLayerP = NULL;
  229.  
  230.             // make the new layer the head
  231.         spriteWorldP->headSpriteLayerP = newSpriteLayerP;
  232.     }
  233.  
  234.         // make the new layer the tail
  235.     spriteWorldP->tailSpriteLayerP = newSpriteLayerP;
  236. }
  237.  
  238.  
  239. ///--------------------------------------------------------------------------------------
  240. //    SWRemoveSpriteLayer
  241. ///--------------------------------------------------------------------------------------
  242.  
  243. SW_PASCAL void SWRemoveSpriteLayer(
  244.     SpriteWorldPtr spriteWorldP,
  245.     SpriteLayerPtr oldSpriteLayerP)
  246. {
  247.         // is there a next layer?
  248.     if (oldSpriteLayerP->nextSpriteLayerP != NULL)
  249.     {
  250.             // link the next layer to the prev layer
  251.         oldSpriteLayerP->nextSpriteLayerP->prevSpriteLayerP = oldSpriteLayerP->prevSpriteLayerP;
  252.     }
  253.     else
  254.     {
  255.             // make the prev layer the tail
  256.         spriteWorldP->tailSpriteLayerP = oldSpriteLayerP->prevSpriteLayerP;
  257.     }
  258.  
  259.         // is there a prev layer?
  260.     if (oldSpriteLayerP->prevSpriteLayerP != NULL)
  261.     {
  262.             // link the prev layer to the next layer
  263.         oldSpriteLayerP->prevSpriteLayerP->nextSpriteLayerP = oldSpriteLayerP->nextSpriteLayerP;
  264.     }
  265.     else
  266.     {
  267.             // make the next layer the head
  268.         spriteWorldP->headSpriteLayerP = oldSpriteLayerP->nextSpriteLayerP;
  269.     }
  270. }
  271.  
  272.  
  273. ///--------------------------------------------------------------------------------------
  274. //    SWSwapSpriteLayer
  275. ///--------------------------------------------------------------------------------------
  276.  
  277. SW_PASCAL void SWSwapSpriteLayer(
  278.     SpriteWorldPtr spriteWorldP,
  279.     SpriteLayerPtr srcSpriteLayerP,
  280.     SpriteLayerPtr dstSpriteLayerP)
  281. {
  282.     register SpriteLayerPtr swapSpriteLayerP;
  283.     
  284.     swapSpriteLayerP = srcSpriteLayerP->nextSpriteLayerP;
  285.     srcSpriteLayerP->nextSpriteLayerP = dstSpriteLayerP->nextSpriteLayerP;
  286.     dstSpriteLayerP->nextSpriteLayerP = swapSpriteLayerP;
  287.  
  288.     swapSpriteLayerP = srcSpriteLayerP->prevSpriteLayerP;
  289.     srcSpriteLayerP->prevSpriteLayerP = dstSpriteLayerP->prevSpriteLayerP;
  290.     dstSpriteLayerP->prevSpriteLayerP = swapSpriteLayerP;
  291.  
  292.     if (srcSpriteLayerP->nextSpriteLayerP == NULL)
  293.     {
  294.         spriteWorldP->tailSpriteLayerP = srcSpriteLayerP;
  295.     }
  296.     else if (srcSpriteLayerP->prevSpriteLayerP == NULL)
  297.     {
  298.         spriteWorldP->headSpriteLayerP = srcSpriteLayerP;
  299.     }
  300.  
  301.     if (dstSpriteLayerP->nextSpriteLayerP == NULL)
  302.     {
  303.         spriteWorldP->tailSpriteLayerP = dstSpriteLayerP;
  304.     }
  305.     else if (dstSpriteLayerP->prevSpriteLayerP == NULL)
  306.     {
  307.         spriteWorldP->headSpriteLayerP = dstSpriteLayerP;
  308.     }
  309. }
  310.  
  311.  
  312. ///--------------------------------------------------------------------------------------
  313. //    SWGetNextSpriteLayer
  314. ///--------------------------------------------------------------------------------------
  315.  
  316. SW_PASCAL SpriteLayerPtr SWGetNextSpriteLayer(
  317.     SpriteWorldPtr spriteWorldP,
  318.     SpriteLayerPtr curSpriteLayerP)
  319. {
  320.     return (curSpriteLayerP == NULL) ?
  321.             spriteWorldP->headSpriteLayerP :
  322.             curSpriteLayerP->nextSpriteLayerP;
  323. }
  324.  
  325.  
  326. ///--------------------------------------------------------------------------------------
  327. //    SWLockSpriteWorld
  328. ///--------------------------------------------------------------------------------------
  329.  
  330. SW_PASCAL void SWLockSpriteWorld(
  331.     SpriteWorldPtr spriteWorldP)
  332. {
  333.     SpriteLayerPtr curSpriteLayerP;
  334.  
  335.     SWLockFrame(spriteWorldP->windowFrameP);
  336.     SWLockFrame(spriteWorldP->backFrameP);
  337.     SWLockFrame(spriteWorldP->loadFrameP);
  338.  
  339.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  340.  
  341.     while (curSpriteLayerP != NULL)
  342.     {
  343.         SWLockSpriteLayer(curSpriteLayerP);
  344.  
  345.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  346.     }
  347. }
  348.  
  349.  
  350. ///--------------------------------------------------------------------------------------
  351. //    SWUnlockSpriteWorld
  352. ///--------------------------------------------------------------------------------------
  353.  
  354. SW_PASCAL void SWUnlockSpriteWorld(
  355.     SpriteWorldPtr spriteWorldP)
  356. {
  357.     SpriteLayerPtr curSpriteLayerP;
  358.  
  359.     SWUnlockFrame(spriteWorldP->windowFrameP);
  360.     SWUnlockFrame(spriteWorldP->backFrameP);
  361.     SWUnlockFrame(spriteWorldP->loadFrameP);
  362.  
  363.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  364.  
  365.     while (curSpriteLayerP != NULL)
  366.     {
  367.         SWUnlockSpriteLayer(curSpriteLayerP);
  368.  
  369.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  370.     }
  371. }
  372.  
  373.  
  374. ///--------------------------------------------------------------------------------------
  375. //    SWSetPortToBackGround
  376. ///--------------------------------------------------------------------------------------
  377.  
  378. SW_PASCAL void SWSetPortToBackGround(
  379.     SpriteWorldPtr spriteWorldP)
  380. {
  381.     SetPort(spriteWorldP->backFrameP->framePort.monoGrafP);
  382. }
  383.  
  384.  
  385. ///--------------------------------------------------------------------------------------
  386. //    SWSetPortToWindow
  387. ///--------------------------------------------------------------------------------------
  388.  
  389. SW_PASCAL void SWSetPortToWindow(
  390.     SpriteWorldPtr spriteWorldP)
  391. {
  392.     SetPort(spriteWorldP->windowFrameP->framePort.monoGrafP);
  393. }
  394.  
  395.  
  396. ///--------------------------------------------------------------------------------------
  397. //    SWSetSpriteWorldEraseProc
  398. ///--------------------------------------------------------------------------------------
  399.  
  400. SW_PASCAL void SWSetSpriteWorldEraseProc(
  401.     SpriteWorldPtr spriteWorldP,
  402.     DrawProcPtr eraseProc)
  403. {
  404.     spriteWorldP->eraseDrawProc = eraseProc;
  405. }
  406.  
  407.  
  408. ///--------------------------------------------------------------------------------------
  409. //    SWSetSpriteWorldDrawProc
  410. ///--------------------------------------------------------------------------------------
  411.  
  412. SW_PASCAL void SWSetSpriteWorldDrawProc(
  413.     SpriteWorldPtr spriteWorldP,
  414.     MaskDrawProcPtr drawProc)
  415. {
  416.     spriteWorldP->screenDrawProc = drawProc;
  417. }
  418.  
  419.  
  420. ///--------------------------------------------------------------------------------------
  421. //    SWUpdateSpriteWorld
  422. ///--------------------------------------------------------------------------------------
  423.  
  424. SW_PASCAL void SWUpdateSpriteWorld(
  425.     SpriteWorldPtr spriteWorldP)
  426. {
  427.     register SpriteLayerPtr curSpriteLayerP;
  428.     register SpritePtr curSpriteP;
  429.     Rect rgnRect;
  430.  
  431.         // the current port should the one in which we are drawing    
  432.     SetPort(spriteWorldP->loadFrameP->framePort.monoGrafP);
  433.  
  434.     (*spriteWorldP->eraseDrawProc)(spriteWorldP->backFrameP,
  435.                                 spriteWorldP->loadFrameP,
  436.                                 &spriteWorldP->loadFrameP->frameRect,
  437.                                 &spriteWorldP->loadFrameP->frameRect);
  438.  
  439.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  440.  
  441.         // iterate through the layers in this world
  442.     while (curSpriteLayerP != NULL)
  443.     {
  444.         curSpriteP = curSpriteLayerP->headSpriteP;
  445.  
  446.             // iterate through the sprites in this layer
  447.         while (curSpriteP != NULL)
  448.         {
  449.             if (curSpriteP->isVisible)
  450.             {
  451.                 if (curSpriteP->curFrameP->maskRgn != NULL)
  452.                 {
  453.                     rgnRect = (**curSpriteP->curFrameP->maskRgn).rgnBBox;
  454.  
  455.                         // move the mask region to the new sprite location
  456.                     OffsetRgn(curSpriteP->curFrameP->maskRgn,
  457.                             (curSpriteP->destFrameRect.left - rgnRect.left) +
  458.                             curSpriteP->curFrameP->offsetPoint.h,
  459.                             (curSpriteP->destFrameRect.top - rgnRect.top) +
  460.                             curSpriteP->curFrameP->offsetPoint.v);
  461.                 }
  462.  
  463.                     // copy the sprite image onto the back drop piece
  464.                 (*curSpriteP->frameDrawProc)(curSpriteP->curFrameP,
  465.                                             spriteWorldP->loadFrameP,
  466.                                             &curSpriteP->curFrameP->frameRect,
  467.                                             &curSpriteP->destFrameRect);
  468.             }
  469.  
  470.             curSpriteP = curSpriteP->nextSpriteP;
  471.         }
  472.  
  473.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  474.     }
  475.  
  476.             // the current port should the one in which we are drawing    
  477.     SetPort(spriteWorldP->windowFrameP->framePort.monoGrafP);
  478.  
  479.     (*spriteWorldP->screenDrawProc)(spriteWorldP->loadFrameP,
  480.                                     spriteWorldP->windowFrameP,
  481.                                     &spriteWorldP->windowFrameP->frameRect,
  482.                                     &spriteWorldP->windowFrameP->frameRect,
  483.                                     NULL);
  484. }
  485.  
  486.  
  487. ///--------------------------------------------------------------------------------------
  488. //    SWProcessSpriteWorld
  489. ///--------------------------------------------------------------------------------------
  490.  
  491. SW_PASCAL void SWProcessSpriteWorld(
  492.     SpriteWorldPtr spriteWorldP)
  493. {
  494.     register SpriteLayerPtr curSpriteLayerP;
  495.     SpriteLayerPtr nextSpriteLayerP;
  496.     register SpritePtr curSpriteP;
  497.     SpritePtr nextSpriteP;
  498.     register FramePtr oldFrameP, newFrameP;
  499.     Rect rgnRect;
  500.     Point spritePoint, oldPoint;
  501.     short horizOffset, vertOffset;
  502.  
  503.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;    
  504.  
  505.         // iterate through the layers in this world
  506.     while (curSpriteLayerP != NULL)
  507.     {
  508.         nextSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  509.         curSpriteP = curSpriteLayerP->headSpriteP;
  510.  
  511.             // iterate through the sprites in this layer
  512.         while (curSpriteP != NULL)
  513.         {
  514.             nextSpriteP = curSpriteP->nextSpriteP;
  515.  
  516.                 // is it time to advance the sprite’s frame?
  517.             if (curSpriteP->frameTimeTask.hasTaskFired)
  518.             {
  519.                 register short horizFrameDelta;
  520.                 register short vertFrameDelta;
  521.  
  522.                 if (curSpriteP->frameAdvance < 0)
  523.                 {
  524.                         // is this the first frame?
  525.                     if (curSpriteP->curFrameIndex <= curSpriteP->firstFrameIndex)
  526.                     {
  527.                             // wrap to the last frame
  528.                         curSpriteP->curFrameIndex = curSpriteP->lastFrameIndex;
  529.                     }
  530.                     else
  531.                     {
  532.                             // advance to next frame
  533.                         curSpriteP->curFrameIndex += curSpriteP->frameAdvance;
  534.                     }
  535.                 }
  536.                 else if (curSpriteP->frameAdvance > 0)
  537.                 {
  538.                         // is this the last frame?
  539.                     if (curSpriteP->curFrameIndex >= curSpriteP->lastFrameIndex)
  540.                     {
  541.                             // wrap to the first frame
  542.                         curSpriteP->curFrameIndex = curSpriteP->firstFrameIndex;
  543.                     }
  544.                     else
  545.                     {
  546.                             // advance to next frame
  547.                         curSpriteP->curFrameIndex += curSpriteP->frameAdvance;
  548.                     }
  549.                 }
  550.  
  551.                     // get new frame
  552.                 newFrameP =    curSpriteP->frameArray[curSpriteP->curFrameIndex];
  553.  
  554.                     // is there a frame callback?
  555.                 if (curSpriteP->frameChangeProc != NULL)
  556.                 {
  557.                         // call it
  558.                     (*curSpriteP->frameChangeProc)(curSpriteP, newFrameP,
  559.                             &curSpriteP->curFrameIndex);
  560.  
  561.                         // make sure the new frame index is in range
  562.                     if (curSpriteP->curFrameIndex < 0)
  563.                     {
  564.                         curSpriteP->curFrameIndex = 0;
  565.                     }
  566.                     else if (curSpriteP->curFrameIndex >= curSpriteP->maxFrames)
  567.                     {
  568.                         curSpriteP->curFrameIndex = curSpriteP->maxFrames - 1;
  569.                     }
  570.                 }
  571.  
  572.                     // change the frame
  573.                 newFrameP =    curSpriteP->frameArray[curSpriteP->curFrameIndex];
  574.  
  575.                     // has the frame actually changed?
  576.                 if (curSpriteP->curFrameP != newFrameP)
  577.                 {
  578.                     oldFrameP = curSpriteP->curFrameP;
  579.                     curSpriteP->curFrameP = newFrameP;
  580.  
  581.                     horizOffset = (curSpriteP->destFrameRect.left - newFrameP->frameRect.left);
  582.                     vertOffset = (curSpriteP->destFrameRect.top - newFrameP->frameRect.top);
  583.  
  584.                     curSpriteP->destFrameRect = newFrameP->frameRect;
  585.  
  586.                     curSpriteP->destFrameRect.left += horizOffset;
  587.                     curSpriteP->destFrameRect.right += horizOffset;
  588.                     curSpriteP->destFrameRect.top += vertOffset;
  589.                     curSpriteP->destFrameRect.bottom += vertOffset;
  590.  
  591.                     curSpriteP->needsToBeDrawn = true;
  592.                 }
  593.  
  594.                 if (curSpriteP->frameTimeInterval > 0)
  595.                 {
  596.                     curSpriteP->frameTimeTask.hasTaskFired = false;
  597.  
  598.                         // reset the time till next frame
  599.                     PrimeTime((QElemPtr)&curSpriteP->frameTimeTask, curSpriteP->frameTimeInterval);
  600.                 }
  601.             }
  602.  
  603.                 // is it time to move the sprite?
  604.             if (curSpriteP->moveTimeTask.hasTaskFired)
  605.             {
  606.                     // is there a movement callback?
  607.                 if (curSpriteP->spriteMoveProc != NULL)
  608.                 {
  609.                     oldPoint = spritePoint;
  610.  
  611.                     spritePoint.h = curSpriteP->destFrameRect.left + curSpriteP->horizMoveDelta;
  612.                     spritePoint.v = curSpriteP->destFrameRect.top + curSpriteP->vertMoveDelta;
  613.  
  614.                         // call it
  615.                     (*curSpriteP->spriteMoveProc)(curSpriteP, &spritePoint);
  616.  
  617.                     if ((spritePoint.h != oldPoint.h) || (spritePoint.v != oldPoint.v))
  618.                     {
  619.                         curSpriteP->destFrameRect.right  = (curSpriteP->destFrameRect.right -
  620.                                                             curSpriteP->destFrameRect.left) +
  621.                                                             spritePoint.h;
  622.                         curSpriteP->destFrameRect.bottom = (curSpriteP->destFrameRect.bottom -
  623.                                                             curSpriteP->destFrameRect.top) +
  624.                                                             spritePoint.v;
  625.                         curSpriteP->destFrameRect.left = spritePoint.h;
  626.                         curSpriteP->destFrameRect.top = spritePoint.v;
  627.  
  628.                         curSpriteP->needsToBeDrawn = true;
  629.                     }
  630.                 }
  631.                 else if ((curSpriteP->horizMoveDelta != 0) || (curSpriteP->vertMoveDelta != 0))
  632.                 {
  633.                         // offset destination rect (way faster than OffsetRect)
  634.                     curSpriteP->destFrameRect.top += curSpriteP->vertMoveDelta;
  635.                     curSpriteP->destFrameRect.left += curSpriteP->horizMoveDelta;
  636.                     curSpriteP->destFrameRect.bottom += curSpriteP->vertMoveDelta;
  637.                     curSpriteP->destFrameRect.right += curSpriteP->horizMoveDelta;
  638.  
  639.                     curSpriteP->needsToBeDrawn = true;
  640.                 }
  641.  
  642.                 if (curSpriteP->moveTimeInterval > 0)
  643.                 {
  644.                     curSpriteP->moveTimeTask.hasTaskFired = false;
  645.  
  646.                         // reset the time till next move
  647.                     PrimeTime((QElemPtr)&curSpriteP->moveTimeTask,
  648.                             curSpriteP->moveTimeInterval);
  649.                 }
  650.             }
  651.  
  652.             if (nextSpriteP != NULL)
  653.             {
  654.                 curSpriteP = nextSpriteP;
  655.             }
  656.             else
  657.             {
  658.                 curSpriteP = curSpriteP->nextSpriteP;
  659.             }
  660.         }
  661.  
  662.         if (nextSpriteLayerP != NULL)
  663.         {
  664.             curSpriteLayerP = nextSpriteLayerP;    
  665.         }
  666.         else
  667.         {
  668.             curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  669.         }
  670.     }
  671. }
  672.  
  673.  
  674. ///--------------------------------------------------------------------------------------
  675. //    SWAnimateSpriteWorld
  676. ///--------------------------------------------------------------------------------------
  677.  
  678. SW_PASCAL void SWAnimateSpriteWorld(
  679.     SpriteWorldPtr spriteWorldP)
  680. {
  681.     register SpriteLayerPtr curSpriteLayerP;
  682.     register SpritePtr curSpriteP;
  683.     Rect rgnRect;
  684.  
  685.         // the current port should the one in which we are drawing    
  686.     SetPort(spriteWorldP->loadFrameP->framePort.monoGrafP);
  687.  
  688.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;    
  689.  
  690.         // iterate through the layers in this world
  691.     while (curSpriteLayerP != NULL)
  692.     {
  693.         curSpriteP = curSpriteLayerP->headSpriteP;
  694.  
  695.             // iterate through the sprites in this layer
  696.         while (curSpriteP != NULL)
  697.         {
  698.             if ((curSpriteP->needsToBeDrawn && curSpriteP->isVisible) ||
  699.                 (curSpriteP->needsToBeErased && !curSpriteP->isVisible))
  700.             {
  701.                     // union last rect and current rect
  702.                     // this way is much faster than UnionRect
  703.                 curSpriteP->deltaFrameRect.top    =    (curSpriteP->oldFrameRect.top <
  704.                                                     curSpriteP->destFrameRect.top) ?
  705.                                                     curSpriteP->oldFrameRect.top :
  706.                                                     curSpriteP->destFrameRect.top;
  707.                 curSpriteP->deltaFrameRect.left    =    (curSpriteP->oldFrameRect.left <
  708.                                                     curSpriteP->destFrameRect.left) ?
  709.                                                     curSpriteP->oldFrameRect.left :
  710.                                                     curSpriteP->destFrameRect.left;
  711.                 curSpriteP->deltaFrameRect.bottom =    (curSpriteP->oldFrameRect.bottom >
  712.                                                     curSpriteP->destFrameRect.bottom) ?
  713.                                                     curSpriteP->oldFrameRect.bottom :
  714.                                                     curSpriteP->destFrameRect.bottom;
  715.                 curSpriteP->deltaFrameRect.right = (curSpriteP->oldFrameRect.right >
  716.                                                     curSpriteP->destFrameRect.right) ?
  717.                                                     curSpriteP->oldFrameRect.right :
  718.                                                     curSpriteP->destFrameRect.right;
  719.  
  720.                     // align the left edge to long word boundary
  721.                 curSpriteP->deltaFrameRect.left &=
  722.                         (spriteWorldP->loadFrameP->leftAlignFactor);
  723.  
  724.                     // align the right edge to long word boundary
  725.                 if ((curSpriteP->deltaFrameRect.right &
  726.                         spriteWorldP->loadFrameP->rightAlignFactor) != 0)
  727.                 {
  728.                     curSpriteP->deltaFrameRect.right +=
  729.                             (spriteWorldP->loadFrameP->rightAlignFactor + 1) -
  730.                             (curSpriteP->deltaFrameRect.right &
  731.                             spriteWorldP->loadFrameP->rightAlignFactor);
  732.                 }
  733.  
  734.                     // copy the back drop piece
  735.                 (*spriteWorldP->eraseDrawProc)(spriteWorldP->backFrameP,
  736.                                              spriteWorldP->loadFrameP,
  737.                                              &curSpriteP->deltaFrameRect,
  738.                                              &curSpriteP->deltaFrameRect);
  739.             }
  740.  
  741.             curSpriteP = curSpriteP->nextSpriteP;
  742.         }
  743.  
  744.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;    
  745.     }
  746.  
  747.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  748.  
  749.         // iterate through the layers in this world
  750.     while (curSpriteLayerP != NULL)
  751.     {
  752.         curSpriteP = curSpriteLayerP->headSpriteP;
  753.  
  754.             // iterate through the sprites in this layer
  755.         while (curSpriteP != NULL)
  756.         {
  757.             if (curSpriteP->isVisible)
  758.             {
  759.                 if (curSpriteP->needsToBeDrawn)
  760.                 {
  761.                     if (curSpriteP->curFrameP->maskRgn != NULL)
  762.                     {
  763.                         rgnRect = (**curSpriteP->curFrameP->maskRgn).rgnBBox;
  764.     
  765.                             // move the mask region to the new sprite location
  766.                         OffsetRgn(curSpriteP->curFrameP->maskRgn,
  767.                                 (curSpriteP->destFrameRect.left - rgnRect.left) +
  768.                                 curSpriteP->curFrameP->offsetPoint.h,
  769.                                 (curSpriteP->destFrameRect.top - rgnRect.top) +
  770.                                 curSpriteP->curFrameP->offsetPoint.v);
  771.                     }
  772.     
  773.                         // copy the sprite image onto the back drop piece
  774.                     (*curSpriteP->frameDrawProc)(curSpriteP->curFrameP,
  775.                                                  spriteWorldP->loadFrameP,
  776.                                                  &curSpriteP->curFrameP->frameRect,
  777.                                                 &curSpriteP->destFrameRect);
  778.                 }
  779.                 else
  780.                 {
  781.                     SWUpdateSpriteOffscreen(spriteWorldP, curSpriteP);
  782.                 }
  783.             }
  784.  
  785.             curSpriteP = curSpriteP->nextSpriteP;
  786.         }
  787.  
  788.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  789.     }
  790.  
  791.         // the current port should the one in which we are drawing    
  792.     SetPort(spriteWorldP->windowFrameP->framePort.monoGrafP);
  793.  
  794.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  795.  
  796.         // iterate through the layers in this world
  797.     while (curSpriteLayerP != NULL)
  798.     {
  799.         curSpriteP = curSpriteLayerP->headSpriteP;
  800.  
  801.             // iterate through the sprites in this layer
  802.         while (curSpriteP != NULL)
  803.         {
  804.             if ((curSpriteP->needsToBeDrawn && curSpriteP->isVisible) ||
  805.                 (curSpriteP->needsToBeErased && !curSpriteP->isVisible))
  806.             {
  807.                     // copy the backdrop+sprite piece from the loader to the screen
  808.                 (*spriteWorldP->screenDrawProc)(spriteWorldP->loadFrameP,
  809.                                                          spriteWorldP->windowFrameP,
  810.                                                          &curSpriteP->deltaFrameRect,
  811.                                                          &curSpriteP->deltaFrameRect,
  812.                                                          curSpriteP->screenMaskRgn);
  813.  
  814.                     // set the delta and last rect to the current rect
  815.                 curSpriteP->deltaFrameRect = curSpriteP->destFrameRect;
  816.                 curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  817.  
  818.                     // this sprite no longer needs to be drawn
  819.                 curSpriteP->needsToBeDrawn = false;
  820.                 curSpriteP->needsToBeErased = false;
  821.             }
  822.  
  823.             curSpriteP = curSpriteP->nextSpriteP;
  824.         }
  825.  
  826.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  827.     }
  828. }
  829.  
  830.  
  831. ///--------------------------------------------------------------------------------------
  832. //    SWUpdateSpriteOffscreen
  833. ///--------------------------------------------------------------------------------------
  834.  
  835. static void SWUpdateSpriteOffscreen(
  836.     SpriteWorldPtr spriteWorldP,
  837.     register SpritePtr srcSpriteP)
  838. {
  839.     Boolean needsRegionOffset = true;
  840.     register SpriteLayerPtr curSpriteLayerP;
  841.     register SpritePtr dstSpriteP;
  842.     Rect rgnRect, srcSectRect, dstSectRect;
  843.  
  844.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  845.  
  846.         // iterate through the layers in this world
  847.     while (curSpriteLayerP != NULL)
  848.     {
  849.         dstSpriteP = curSpriteLayerP->headSpriteP;
  850.  
  851.             // iterate through the sprites in this layer
  852.         while (dstSpriteP != NULL)
  853.         {
  854.             if ((dstSpriteP != srcSpriteP) &&
  855.                 ((dstSpriteP->needsToBeDrawn && dstSpriteP->isVisible) ||
  856.                 (dstSpriteP->needsToBeErased && !dstSpriteP->isVisible)))
  857.             {
  858.                     // are the sprite’s rectangles overlapping?
  859.                 if (!((srcSpriteP->destFrameRect.top >= dstSpriteP->deltaFrameRect.bottom) ||
  860.                          (srcSpriteP->destFrameRect.bottom <= dstSpriteP->deltaFrameRect.top) ||
  861.                          (srcSpriteP->destFrameRect.left >= dstSpriteP->deltaFrameRect.right) ||
  862.                          (srcSpriteP->destFrameRect.right <= dstSpriteP->deltaFrameRect.left)))
  863.                 {    
  864.                     if (needsRegionOffset && (srcSpriteP->curFrameP->maskRgn != NULL))
  865.                     {
  866.                         rgnRect = (**srcSpriteP->curFrameP->maskRgn).rgnBBox;
  867.                         
  868.                             // move the mask region to the new sprite location
  869.                         OffsetRgn(srcSpriteP->curFrameP->maskRgn,
  870.                                     (srcSpriteP->destFrameRect.left - rgnRect.left) +
  871.                                     srcSpriteP->curFrameP->offsetPoint.h,
  872.                                     (srcSpriteP->destFrameRect.top - rgnRect.top) +
  873.                                     srcSpriteP->curFrameP->offsetPoint.v);
  874.  
  875.                         needsRegionOffset = false;
  876.                     }
  877.  
  878.                     dstSectRect.left =
  879.                             (srcSpriteP->destFrameRect.left > dstSpriteP->deltaFrameRect.left)
  880.                             ? srcSpriteP->destFrameRect.left : dstSpriteP->deltaFrameRect.left;
  881.  
  882.                     dstSectRect.top =
  883.                             (srcSpriteP->destFrameRect.top > dstSpriteP->deltaFrameRect.top)
  884.                             ? srcSpriteP->destFrameRect.top : dstSpriteP->deltaFrameRect.top;
  885.  
  886.                     dstSectRect.right =
  887.                             (srcSpriteP->destFrameRect.right < dstSpriteP->deltaFrameRect.right)
  888.                             ? srcSpriteP->destFrameRect.right : dstSpriteP->deltaFrameRect.right;
  889.  
  890.                     dstSectRect.bottom =
  891.                             (srcSpriteP->destFrameRect.bottom < dstSpriteP->deltaFrameRect.bottom)
  892.                             ? srcSpriteP->destFrameRect.bottom : dstSpriteP->deltaFrameRect.bottom;
  893.  
  894.                     srcSectRect = dstSectRect;
  895.  
  896.                     srcSectRect.left +=
  897.                             (srcSpriteP->curFrameP->frameRect.left - srcSpriteP->destFrameRect.left);
  898.  
  899.                     srcSectRect.right +=
  900.                             (srcSpriteP->curFrameP->frameRect.left - srcSpriteP->destFrameRect.left);
  901.  
  902.                     srcSectRect.top +=
  903.                             (srcSpriteP->curFrameP->frameRect.top - srcSpriteP->destFrameRect.top);
  904.  
  905.                     srcSectRect.bottom +=
  906.                             (srcSpriteP->curFrameP->frameRect.top - srcSpriteP->destFrameRect.top);
  907.  
  908.                         // copy a piece of the sprite image onto the back drop piece
  909.                     (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP,
  910.                                                         spriteWorldP->loadFrameP,
  911.                                                         &srcSectRect,
  912.                                                         &dstSectRect);
  913.                 }
  914.             }
  915.  
  916.             dstSpriteP = dstSpriteP->nextSpriteP;
  917.         }
  918.  
  919.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  920.     }
  921. }
  922.